package org.drools.compiler.kie;

import org.drools.compiler.compiler.io.File;
import org.drools.compiler.compiler.io.FileSystem;
import org.drools.compiler.compiler.io.Folder;
import org.drools.compiler.compiler.io.memory.MemoryFileSystem;
import org.drools.compiler.compiler.io.memory.MemoryFolder;
import org.drools.core.util.StringUtils;
import org.junit.Test;

import java.io.ByteArrayInputStream;
import java.io.IOException;

import static org.junit.Assert.*;
import static org.junit.Assert.assertEquals;

public class MemoryFileTest {

    @Test
    public void testFileCreation() throws IOException {
        FileSystem fs = new MemoryFileSystem();

        Folder mres = fs.getFolder( "src/main/java/org/domain" );

        File f1 = mres.getFile( "MyClass.java" );
        f1.create( new ByteArrayInputStream( "ABC".getBytes() ) );

        mres.create();

        f1 = mres.getFile( "MyClass.java" );
        assertTrue( f1.exists());

        f1.create( new ByteArrayInputStream( "ABC".getBytes() ) );
        f1 = mres.getFile( "MyClass.java" );
        assertTrue( f1.exists() );

        assertEquals( "ABC", StringUtils.toString( f1.getContents() ) );

        f1.create( new ByteArrayInputStream( "ABC".getBytes() ) );

        f1.setContents( new ByteArrayInputStream( "DEF".getBytes() ) );
        assertEquals( "DEF", StringUtils.toString( f1.getContents() ) );
    }

    @Test
    public void testFileRemoval() throws IOException {
        FileSystem fs = new MemoryFileSystem();

        Folder mres = fs.getFolder( "src/main/java/org/domain" );
        mres.create();

        File f1 = mres.getFile( "MyClass.java" );
        f1.create( new ByteArrayInputStream( "ABC".getBytes() ) );
        assertTrue( f1.exists() );
        assertEquals( "ABC", StringUtils.toString( f1.getContents() ) );

        fs.remove( f1 );

        f1 = mres.getFile( "MyClass.java" );
        assertFalse( f1.exists() );

        try {
            f1.getContents();
            fail( "Should throw IOException" );
        } catch( IOException e ) {

        }
    }

    @Test
    public void testFilePath() {
        FileSystem fs = new MemoryFileSystem();

        Folder mres = fs.getFolder( "src/main/java/org/domain" );

        File f1 = mres.getFile( "MyClass.java" );
        assertEquals( "src/main/java/org/domain/MyClass.java",
                f1.getPath().toPortableString() );
    }

    @Test
    public void testRelativeToParentFilePath() {
        FileSystem fs = new MemoryFileSystem();

        Folder mres = fs.getFolder( "src/main/java/org/domain" );
        Folder f2 = fs.getFolder( "src/main/java/org/domain/f1/f2/" );

        File f1 = mres.getFile( "MyClass.java" );
        assertEquals( "../../MyClass.java",
                f1.getPath().toRelativePortableString( f2.getPath() ) );
    }

    @Test
    public void testRelativeToBranchFilePath() {
        FileSystem fs = new MemoryFileSystem();

        Folder mres = fs.getFolder( "src/main/java/org/domain" );
        Folder f2 = fs.getFolder( "src/main/resources/org/domain/" );

        File f1 = mres.getFile( "MyClass.java" );
        assertEquals( "../../../java/org/domain/MyClass.java",
                f1.getPath().toRelativePortableString( f2.getPath() ) );
    }

    @Test
    public void testGetParentWithLeadingAndTrailingSlash() {
        MemoryFileSystem mfs = new MemoryFileSystem();
        assertEquals( "", new MemoryFolder( mfs, "/src" ).getParent().getPath().toPortableString() );

        assertEquals( "", new MemoryFolder( mfs, "src/" ).getParent().getPath().toPortableString() );

        assertEquals( "", new MemoryFolder( mfs, "/src/" ).getParent().getPath().toPortableString() );

        assertEquals( "src", new MemoryFolder( mfs, "/src/main" ).getParent().getPath().toPortableString() );

        assertEquals( "src", new MemoryFolder( mfs, "src/main/" ).getParent().getPath().toPortableString() );

        assertEquals( "src", new MemoryFolder( mfs, "/src/main/" ).getParent().getPath().toPortableString() );

        assertEquals( "src/main", new MemoryFolder( mfs, "/src/main/java" ).getParent().getPath().toPortableString() );

        assertEquals( "src/main", new MemoryFolder( mfs, "src/main/java/" ).getParent().getPath().toPortableString() );

        assertEquals( "src/main", new MemoryFolder( mfs, "/src/main/java/" ).getParent().getPath().toPortableString() );
        assertEquals( "src", new MemoryFolder( mfs, "/src/main/java/" ).getParent().getParent().getPath().toPortableString() );
    }

    @Test
    public void testFolderGetParent() {
        FileSystem fs = new MemoryFileSystem();

        Folder mres = fs.getFolder( "src/main/resources" );
        mres.create();

        assertEquals( "src/main", mres.getParent().getPath().toPortableString() );

        assertEquals( "src", mres.getParent().getParent().getPath().toPortableString() );

    }

    @Test
    public void testNestedRelativePath() {
        FileSystem fs = new MemoryFileSystem();

        Folder f1 = fs.getFolder( "src/main/java" );
        Folder f2 = fs.getFolder( "src/main/java/org" );

        f1.create();
        f2.create();

        assertEquals( "org", f2.getPath().toRelativePortableString( f1.getPath() ) );

        fs = new MemoryFileSystem();

        f1 = fs.getFolder( "src/main/java" );
        f2 = fs.getFolder( "src/main/java/org/drools/reteoo" );

        f1.create();
        f2.create();

        assertEquals( "org/drools/reteoo", f2.getPath().toRelativePortableString( f1.getPath() ) );
    }

    @Test
    public void testNestedRelativePathReverseArguments() {
        FileSystem fs = new MemoryFileSystem();

        Folder f1 = fs.getFolder( "src/main/java/org" );
        Folder f2 = fs.getFolder( "src/main/java/" );

        f1.create();
        f2.create();

        assertEquals( "..", f2.getPath().toRelativePortableString( f1.getPath() ) );

        fs = new MemoryFileSystem();

        f1 = fs.getFolder( "src/main/java/org/drools/reteoo" );
        f2 = fs.getFolder( "src/main/java" );

        f1.create();
        f2.create();

        assertEquals( "../../..", f2.getPath().toRelativePortableString( f1.getPath() ) );
    }

    @Test
    public void testNestedRelativeDifferentPath() {
        FileSystem fs = new MemoryFileSystem();

        Folder f1 = fs.getFolder( "src/main/java" );
        Folder f2 = fs.getFolder( "src/main/resources" );

        f1.create();
        f2.create();

        assertEquals( "../resources", f2.getPath().toRelativePortableString( f1.getPath() ) );

        fs = new MemoryFileSystem();

        f1 = fs.getFolder( "src/main/java/org/drools" );
        f2 = fs.getFolder( "src/main/resources/org/drools/reteoo" );

        f1.create();
        f2.create();

        assertEquals( "../../../resources/org/drools/reteoo", f2.getPath().toRelativePortableString( f1.getPath() ) );
    }


    @Test
    public void testFolderRemoval() throws IOException {
        FileSystem fs = new MemoryFileSystem();

        Folder fld = fs.getFolder( "src/main/resources/org/domain" );
        fld.create();

        fld = fs.getFolder( "src/main" );
        File file = fld.getFile( "MyClass1.java" );
        file.create( new ByteArrayInputStream( "ABC1".getBytes() ) );
        file = fld.getFile( "MyClass2.java" );
        file.create( new ByteArrayInputStream( "ABC2".getBytes() ) );

        fld = fs.getFolder( "src/main/resources/org" );
        file = fld.getFile( "MyClass3.java" );
        file.create( new ByteArrayInputStream( "ABC3".getBytes() ) );
        file = fld.getFile( "MyClass4.java" );
        file.create( new ByteArrayInputStream( "ABC4".getBytes() ) );


        fld = fs.getFolder( "src/main/resources/org/domain" );
        file = fld.getFile( "MyClass4.java" );
        file.create( new ByteArrayInputStream( "ABC5".getBytes() ) );

        assertTrue( fs.getFolder( "src/main" ).exists() );
        assertTrue( fs.getFile( "src/main/MyClass1.java" ).exists() );
        assertTrue( fs.getFile( "src/main/MyClass2.java" ).exists() );
        assertTrue( fs.getFile( "src/main/resources/org/MyClass3.java" ).exists() );
        assertTrue( fs.getFile( "src/main/resources/org/MyClass4.java" ).exists() );
        assertTrue( fs.getFile( "src/main/resources/org/domain/MyClass4.java" ).exists() );

        fs.remove( fs.getFolder( "src/main" ) );

        assertFalse( fs.getFolder( "src/main" ).exists() );
        assertFalse( fs.getFile( "src/main/MyClass1.java" ).exists() );
        assertFalse( fs.getFile( "src/main/MyClass2.java" ).exists() );
        assertFalse( fs.getFile( "src/main/resources/org/MyClass3.java" ).exists() );
        assertFalse( fs.getFile( "src/main/resources/org/MyClass4.java" ).exists() );
        assertFalse( fs.getFile( "src/main/resources/org/domain/MyClass4.java" ).exists() );
    }


    @Test
    public void trimLeadingAndTrailing() {
        assertEquals("", MemoryFolder.trimLeadingAndTrailing(""));
        assertEquals("src/main", MemoryFolder.trimLeadingAndTrailing("/src/main"));
        assertEquals("src/main", MemoryFolder.trimLeadingAndTrailing("src/main/"));
        assertEquals("src/main", MemoryFolder.trimLeadingAndTrailing("/src/main/"));
    }





}
